]> vault307.fbx.one Git - Sensory_Wall.git/blob - circuitPython/waterfall_visualizer/CircuitPython 7.x/code.py
more sensory wall projects
[Sensory_Wall.git] / circuitPython / waterfall_visualizer / CircuitPython 7.x / code.py
1 # SPDX-FileCopyrightText: 2021 Liz Clark for Adafruit Industries
2 #
3 # SPDX-License-Identifier: MIT
4
5 '''Adapted from the FFT Example: Waterfall Spectrum Analyzer
6 by Jeff Epler
7 https://learn.adafruit.com/ulab-crunch-numbers-fast-with-circuitpython/overview '''
8
9 import array
10 import board
11 import audiobusio
12 import busio
13 from ulab import numpy as np
14 from ulab.scipy.signal import spectrogram
15 import adafruit_is31fl3741
16 from adafruit_is31fl3741.adafruit_rgbmatrixqt import Adafruit_RGBMatrixQT
17
18 # Manually declare I2c (not board.I2C()) to access 1 MHz speed for
19 i2c = busio.I2C(board.SCL, board.SDA, frequency=1000000)
20 # Declare is31 w/buffering preferred (low RAM will fall back on unbuffered)
21 is31 = Adafruit_RGBMatrixQT(i2c, allocate=adafruit_is31fl3741.PREFER_BUFFER)
22 # In buffered mode, MUST use show() to refresh matrix (see line 94)
23
24 # brightness for the RGBMatrixQT
25 # set to about 20%
26 is31.set_led_scaling(0x19)
27 is31.global_current = 0x03
28 is31.enable = True
29
30 # array of colors for the LEDs
31 # goes from purple to red
32 # gradient generated using https://colordesigner.io/gradient-generator
33 heatmap = [0xb000ff,0xa600ff,0x9b00ff,0x8f00ff,0x8200ff,
34 0x7400ff,0x6500ff,0x5200ff,0x3900ff,0x0003ff,
35 0x0003ff,0x0047ff,0x0066ff,0x007eff,0x0093ff,
36 0x00a6ff,0x00b7ff,0x00c8ff,0x00d7ff,0x00e5ff,
37 0x00e0ff,0x00e6fd,0x00ecf6,0x00f2ea,0x00f6d7,
38 0x00fac0,0x00fca3,0x00fe81,0x00ff59,0x00ff16,
39 0x00ff16,0x45ff08,0x62ff00,0x78ff00,0x8bff00,
40 0x9bff00,0xaaff00,0xb8ff00,0xc5ff00,0xd1ff00,
41 0xedff00,0xf5eb00,0xfcd600,0xffc100,0xffab00,
42 0xff9500,0xff7c00,0xff6100,0xff4100,0xff0000,
43 0xff0000,0xff0000]
44
45 # size of the FFT data sample
46 fft_size = 64
47
48 # setup for onboard mic
49 mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA,
50 sample_rate=16000, bit_depth=16)
51
52 # use some extra sample to account for the mic startup
53 samples_bit = array.array('H', [0] * (fft_size+3))
54
55 # sends visualized data to the RGB matrix with colors
56 def waves(data, y):
57 offset = max(0, (13-len(data))//2)
58
59 for x in range(min(13, len(data))):
60 is31.pixel(x+offset, y, heatmap[int(data[x])])
61
62 # main loop
63 def main():
64 # value for audio samples
65 max_all = 10
66 # variable to move data along the matrix
67 scroll_offset = 0
68 # setting the y axis value to equal the scroll_offset
69 y = scroll_offset
70
71 while True:
72 # record the audio sample
73 mic.record(samples_bit, len(samples_bit))
74 # send the sample to the ulab array
75 samples = np.array(samples_bit[3:])
76 # creates a spectogram of the data
77 spectrogram1 = spectrogram(samples)
78 # spectrum() is always nonnegative, but add a tiny value
79 # to change any zeros to nonzero numbers
80 spectrogram1 = np.log(spectrogram1 + 1e-7)
81 spectrogram1 = spectrogram1[1:(fft_size//2)-1]
82 # sets range of the spectrogram
83 min_curr = np.min(spectrogram1)
84 max_curr = np.max(spectrogram1)
85 # resets values
86 if max_curr > max_all:
87 max_all = max_curr
88 else:
89 max_curr = max_curr-1
90 min_curr = max(min_curr, 3)
91 # stores spectrogram in data
92 data = (spectrogram1 - min_curr) * (51. / (max_all - min_curr))
93 # sets negative numbers to zero
94 data = data * np.array((data > 0))
95 # resets y
96 y = scroll_offset
97 # runs waves to write data to the LED's
98 waves(data, y)
99 # updates scroll_offset to move data along matrix
100 scroll_offset = (y + 1) % 9
101 # writes data to the RGB matrix
102 is31.show()
103
104 main()